package com.estock.platform.task;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.springframework.stereotype.Component;

import com.estock.common.model.security.RealTimeTrans;
import com.estock.common.model.security.Stock;
import com.estock.common.util.CommonUtil;
import com.estock.common.util.support.ESLogger;
import com.estock.platform.http.SinaStockBulkConn;
import com.estock.platform.http.response.SinaRealTimeStockBulkResponse;
import com.estock.platform.manager.CacheManager;
import com.estock.platform.manager.DBManager;
import com.estock.platform.task.support.ESJob;

/**
 * We control cron task scheduler manually, instead of annotation
 * 
 * @author richard
 *
 */
@Component
public class RealTimeStockGetter extends ESJob {
	
	/** Logger */
	private static ESLogger logger = ESLogger.getLogger(RealTimeStockGetter.class);
	
	private static final int BULK_SIZE = 100;
	private List<Stock> bulkStocks = new ArrayList<Stock>(BULK_SIZE);	
	private List<RealTimeTrans> responseTrans = new ArrayList<RealTimeTrans>();
	
	protected static ExecutorService executor;
	int bulkSize = 0;
	int requestedNum = 0;

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
    public void executeJob() {
		logger.info("start executing job: RealTimeStockGetter at " + new Date());

		List<Stock> allStocks = getAllStocks();
		executor = Executors.newCachedThreadPool(new HandlerThreadFactory());
		while (requestedNum < allStocks.size()) {
			while (bulkSize < BULK_SIZE && requestedNum < allStocks.size()) {
				bulkStocks.add(allStocks.get(requestedNum));
				bulkSize++;
				requestedNum++;
			}
			
			try {
				logger.info("start new thread of getting realtime data from sina.");
				Thread thread = new RealTimeSinaConnThread(new ArrayList<Stock>(bulkStocks));
				executor.execute(thread);
			} catch (Exception e) {
				// continue
			}
			
			bulkSize = 0;
			bulkStocks.clear();
		}

		executor.shutdown();
		while (!executor.isTerminated()) {
			//
		}
		DBManager.getInstance().saveOrUpdateAll((List)responseTrans);
		
	}
	
	class RealTimeSinaConnThread extends Thread {
		private List<Stock> stocks;
		public RealTimeSinaConnThread(List<Stock> stocks) {
			this.stocks = stocks;
		}
		
		@Override
		public void run() {
			SinaRealTimeStockBulkResponse response;
			try {
				response = (SinaRealTimeStockBulkResponse) 
						new SinaStockBulkConn().request(new ArrayList<Stock>(stocks), true);
			} catch (Exception e1) {
				throw new RuntimeException("Error in request realtime trans data from sina.");
			}
			List<RealTimeTrans> realTimes = response.getRealTimeTrans();
			responseTrans.addAll(realTimes);
		}
	}
	
	protected List<Stock> getAllStocks() {
		return new ArrayList<Stock>(CacheManager.getInstance().getStocks());
	}
	
	
	public static void main(String[] args) {
		CommonUtil.isUnitTest = true;
		RealTimeStockGetter instance = new RealTimeStockGetter() {
			protected List<Stock> getAllStocks() {
				List<Stock> stocks = new ArrayList<Stock>();
				stocks.add(new Stock("000625", "", 2));
				return stocks;
			}
		};
		instance.executeJob();
		CommonUtil.isUnitTest = false;
	}

}
